home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagd_f.zip / DOS.SWG / 0007_Execute & Redirection.pas < prev    next >
Pascal/Delphi Source File  |  1993-05-31  |  19KB  |  498 lines

  1.  
  2. ------------------------------------------------------------------------
  3.  
  4. Echo Flag :         Permanent: N       Export: N      Personal Read: N
  5.  
  6.  BBS: IN-TECH         Conference: PASCAL          Imported: 11/14/1991
  7.   To: DAVID HICKEY                    Num: 1442       Date: 10/31/1991
  8. From: MARK OUELLET                     Re: 0          Time: 10:51 pm
  9. Subj: >NUL REDIRECTION               Prvt: N          Read: N
  10.  
  11.     On 27 Oct 91, you, David Hickey, of 1:261/1108.0 wrote...
  12.  
  13.  DH> From the DOS prompt, I can redirect things easily.  But when I try it in 
  14.  DH> my program, it doesn't work at all.  Here's what I'm doing:
  15.  DH> 
  16.  DH> EXEC ('C:\Pkzip.Exe', '-o c:\ra\ra.zip c:\ra\ralogs\ra.log >nul');
  17.  DH> 
  18.  DH> The problem is that the information from Pkzip is not being redirected 
  19.  DH> to NUL
  20.  DH> like I want it to.  It's obviously got to be something I'm not doing 
  21.  DH> right. Anyone know what it is?  I've tried everything I can think of.
  22.  
  23. David,
  24.         This might help you,
  25.  
  26. Msg#:20994 *> PASCAL  Echo <*
  27. 03/17/89 03:15:00
  28. From: ROSS WENTWORTH
  29.   To: NORBERT LANGE
  30. Subj: REPLY TO MSG# 20986 (RE: REDIRECTING STDERR)
  31.  > I'd appreciate seeing some code.  I've tried this before,
  32.  > using a couple different methods, and couldn't seem to get
  33.  > DOS to like redirecting StdErr.  I tried the $45 (Duplicate
  34.  > File Handle) function as well with no success.
  35.  
  36. Ok, here's a routine that can be easily modified to do the job. It replaces 
  37. EXEC from the DOS unit and checks the "command line" for the redirection 
  38. symbols ('>' and '<').  One minor change and it will redirect STDERR to the 
  39. file (see comment below).
  40. {=============================================================}
  41. Unit Execute;
  42.  
  43. Interface
  44.  
  45. Procedure Exec(Path,CmdLine : String);
  46.  
  47. Implementation
  48.  
  49. Uses
  50.   Dos;
  51.  
  52. Function ExtractFileName(Var Line : String;Index : Integer) : String;
  53.  
  54. Var
  55.   Temp : String;
  56.  
  57. Begin
  58.   Delete(Line,Index,1);
  59.   While (Index <= Length(Line)) AND (Line[Index] = ' ')
  60.     Do Delete(Line,Index,1);
  61.   Temp := '';
  62.   While (Index <= Length(Line)) AND (Line[Index] <> ' ') Do
  63.   Begin
  64.     Temp := Temp + Line[Index];
  65.     Delete(Line,Index,1);
  66.   End;
  67.   ExtractFileName := Temp;
  68. End;
  69.  
  70. Procedure CloseHandle(Handle : Word);
  71.  
  72. Var
  73.   Regs : Registers;
  74.  
  75. Begin
  76.   With Regs Do
  77.   Begin
  78.     AH := $3E;
  79.     BX := Handle;
  80.     MsDos(Regs);
  81.   End;
  82. End;
  83.  
  84. Procedure Duplicate(SourceHandle : Word;Var TargetHandle : Word);
  85.  
  86. Var
  87.   Regs : Registers;
  88.  
  89. Begin
  90.   With Regs Do
  91.   Begin
  92.     AH := $45;
  93.     BX := SourceHandle;
  94.     MsDos(Regs);
  95.     TargetHandle := AX;
  96.   End;
  97. End;
  98.  
  99. Procedure ForceDuplicate(SourceHandle : Word;Var TargetHandle : Word);
  100.  
  101. Var
  102.   Regs : Registers;
  103.  
  104. Begin
  105.   With Regs Do
  106.   Begin
  107.     AH := $46;
  108.     BX := SourceHandle;
  109.     CX := TargetHandle;
  110.     MsDos(Regs);
  111.     TargetHandle := AX;
  112.   End;
  113. End;
  114.  
  115. Procedure Exec(Path,CmdLine : String);
  116.  
  117. Var
  118.   StdIn   : Word;
  119.   Stdout  : Word;
  120.   Index   : Integer;
  121.   FName   : String[80];
  122.   InFile  : Text;
  123.   OutFile : Text;
  124.  
  125.   InHandle  : Word;
  126.   OutHandle : Word;
  127.          { ===============>>>> }   { change below for STDERR }
  128. Begin
  129.   StdIn := 0;
  130.   StdOut := 1;                    { change to 2 for StdErr       }
  131.   Duplicate(StdIn,InHandle);      { duplicate standard input     }
  132.   Duplicate(StdOut,OutHandle);    { duplicate standard output    }
  133.   Index := Pos('>',CmdLine);
  134.   If Index > 0 Then               { check for output redirection }
  135.   Begin
  136.     FName := ExtractFileName(CmdLine,Index);  { get output file name }
  137.     Assign(OutFile,FName);                    { open a text file      }
  138.     Rewrite(OutFile);                         { .. for output         }
  139.     ForceDuplicate(TextRec(OutFile).Handle,StdOut);{ make output same }
  140.   End;
  141.   Index := Pos('<',CmdLine);
  142.   If Index > 0 Then               { check for input redirection }
  143.   Begin
  144.     FName := ExtractFileName(CmdLine,Index);  { get input file name }
  145.     Assign(InFile,FName);                     { open a text file    }
  146.     Reset(InFile);                            { for input           }
  147.     ForceDuplicate(TextRec(InFile).Handle,StdIn);  { make input same }
  148.   End;
  149.   DOS.Exec(Path,CmdLine);           { run EXEC }
  150.   ForceDuplicate(InHandle,StdIn);   { put standard input back to keyboard }
  151.   ForceDuplicate(OutHandle,StdOut); { put standard output back to screen  }
  152.   CloseHandle(InHandle);            { close the redirected input file     }
  153.   CloseHandle(OutHandle);           { close the redirected output file    }
  154. End;
  155.  
  156. End.
  157.  
  158. {===============================================================}
  159.  
  160. Use it exactly as you would the normal EXEC procedure:
  161.  
  162.   Exec('MASM.EXE','mystuff.asm');
  163.  
  164. To activate redirection simply add the redirection symbols, etc:
  165.  
  166.   Exec('MASM.EXE',mystuff.asm >err.lst');
  167.  
  168.  
  169. One note of caution.  This routine temporarily uses extra handles.  It'
  170. s either
  171. two or four more.  The various books I have are not clear as two whether 
  172. duplicated handles 'count' or not. My guess is yes.  If you don't plan on 
  173. redirecting STDIN then remove all the code for duplicating it to cut your
  174. handle overhead in half.
  175.  
  176.                                     Ross Wentworth
  177.  
  178. +++ FD 2.00
  179.  Origin: St Dymphna's Retreat via Torrance BBS 213-370-9027 (1:102/345.1)
  180.  
  181.         Best regards,
  182.         Mark Ouellet.
  183.  
  184.  
  185. --- ME2
  186.  * Origin: The Doctor's Tardis, A point in time!! (Fidonet 1:240/1.4)
  187. ==============================================================================
  188.  BBS: «« The Information and Technology Exchan
  189.   To: BUTCH ADAMS                  Date: 12-10─91 (18:00)
  190. From: RUSS PARKS                 Number: 3982   [101] PASCAL
  191. Subj: EXEC()                     Status: Public
  192. ------------------------------------------------------------------------------
  193. * In a bleating, agonizing plea to All, Butch Adams groaned:
  194.  
  195. BA>       I'm wondering if I can get some insight as to how to
  196. BA>use the Exec() command in TP6. What I'm trying to do is this:
  197. BA> Exec('Type Filename|sort > newfilename', '');
  198. BA>I've even tried this:
  199. BA> Exec('Type', 'filename|sort > newfilename');
  200.  
  201.  Close, but no cigar :-) Try something like this:
  202.         Exec('command.com', '/c type filename | sort > newfilename');
  203.  
  204.  The first parameter is the path to the program to be run. In this
  205. case, 'TYPE' is an internal DOS command so you need to run
  206. COMMAND.COM. The second parameter is a string with the command
  207. line arguments you want to pass to the program.
  208.   P.S.: The '/c' part of the parameters tells COMMAND.COM to execute
  209. the command, then exit back to the program that originally
  210. called the COMMAND.COM. It's like loading COMMAND.COM, running
  211. a program, then typing 'EXIT'.
  212. Besta'Luck,
  213. Russ
  214.  
  215. ---
  216.  * Origin: Objectively.Speak('Turbo Pascal 6.0, YEAH!'); (1:170/212)
  217. ==============================================================================
  218.  BBS: «« The Information and Technology Exchan
  219.   To: BUTCH ADAMS                  Date: 12-10─91 (21:07)
  220. From: MIKE COPELAND              Number: 4000   [101] PASCAL
  221. Subj: EXEC()                     Status: Public
  222. ------------------------------------------------------------------------------
  223.  BA>       I'm wondering if I can get some insight as to how to use the
  224.  BA>Exec() command in TP6. What I'm trying to do is this:
  225.  
  226.  BA> Exec('Type Filename|sort > newfilename', '');
  227.  
  228.  BA>I've even tried this:
  229.  
  230.  BA> Exec('Type', 'filename|sort > newfilename');
  231.  
  232.  BA>But still no result. Are we able to execute internal commands from
  233.  BA>within a TP program? I've tried loading Command.Com first but all I get
  234.  BA>is the shell to come up and sit there with a C> staring back at me. I
  235.  BA>would appreciate any help with this.
  236.  
  237.    The process to execute any DOS-callable program/command is more than
  238. you're doing/showing here. Try the following:
  239.  
  240. {$M 4096,0,0}  { allocate space for the child process }
  241.  
  242.   SwapVectors;
  243.   Exec (GetEnv('COMSPEC'),'/C Type filename|sort > newfile');
  244.   SwapVectors;
  245.   if DosError > 0 then  { check the result of Exec }
  246.     You_Have_A_Problem;
  247.   if DosExitCode <> 0 then
  248.     You_Have_A_Different_Problem;
  249.   { If you get here, everything's okay... }
  250.  
  251.    Read the manual about SwapVectors, DosError, DosExitCode, GetEnv,
  252. Exec, the $M parameter, and all the stuff you don't understand here...
  253.  
  254.  
  255. --- msged 2.07
  256.  * Origin: Hello, Keyboard, my old friend... (1:114/18.10)
  257. ==============================================================================
  258.  BBS: «« The Information and Technology Exchan
  259.   To: ANDREW PARK                  Date: 12-10─91 (21:15)
  260. From: MIKE COPELAND              Number: 4001   [101] PASCAL
  261. Subj: PASCAL                     Status: Public
  262. ------------------------------------------------------------------------------
  263.  AP>It's quite simple.
  264.  AP>Here's an example
  265.  AP>{$M,1025,0,0}  <-- I don't know what this means but you need anyways
  266.  
  267.    Well, it's very important: it states how much Stack, Heap_Min, and
  268. Heap_Max space you're reserving for the program to use (and how
  269. much space you're leaving for the child process to execute in).
  270. The last (2nd 0) is the most important, since failing to reduce
  271. this from the default of ALL memory will PREVENT the Exec from
  272. having any memory to do its work within. So, setting it to 0
  273. will say "reserve ALL of available memory (except for what's
  274. used by my program itself) for the DOS call I'm going to make
  275. from within my program".
  276.    If you don't do this, it defaults to 640K - meaning "reserve NO
  277. memory for the exec".
  278.  
  279.  AP>Program Copying;
  280.  AP>Uses dos;
  281.  AP>begin
  282.  AP>  exec ('Command.com','copy a:*.* b:');
  283.       Exec (GetEnv('COMSPEC'),'/C copy a:* b:*');
  284.  AP>end.
  285.  AP>Something like that.  See the manual for Exec section.
  286.  
  287.    You should also wrap that Exec call within a pair of SwapVectors
  288. statements...before and after. Furthermore, it's a good idea to
  289. check DosError and DosExitCode after the action, so see if any
  290. problems occurred.
  291.    Exec is very useful, but it carries a lot of "baggage" when used...
  292.  
  293. --- msged 2.07
  294.  * Origin: Hello, Keyboard, my old friend... (1:114/18.10)
  295. ==============================================================================
  296.  BBS: «« The Information and Technology Exchan
  297.   To: KEVIN HIGGINS                Date: 01-04─92 (09:58)
  298. From: MARK OUELLET               Number: 4088   [101] PASCAL
  299. Subj: RE: HEAP KNOWLEDGE         Status: Public
  300. ------------------------------------------------------------------------------
  301.     On 29 Dec 91, you, Kevin Higgins, of 1:128/74.0 wrote...
  302.  
  303.  KH> I still don't understand full use of the {$M} compiler directive.
  304.  KH> The Pascal tome I have says nothing other than if you don't use New() or
  305.  KH> GetMem() to set the HeapMin and HeapMax to 0. But it never says what to
  306.  KH> set it to if you DO you New or GetMem. Nor could I find any reference on
  307.  KH> ideal settings for a small program which Exec's another fairly small
  308.  KH> program....
  309.  
  310. Kevin,
  311.         New() and GetMem() are used to allocate space
  312. (memory) off the heap (That which is left of the 640 K of
  313. dos memory after your program is loaded and DOS and your
  314. TSRs ect...) for variables that are created AT RUNTIME.
  315. Variables you declare in the usual way ie: Var X : Integer;
  316. allready have space allocated to them.
  317.  
  318.         The heap is used to allocate memory to dynamic
  319. variables ie: variables accessed through the use of
  320. pointers. These need to have memory allocated to them
  321. (Unless you are using the pointer to access a region of
  322. memory that allready contains information such as the
  323. keyboard buffer etc... those allready have memory allocated
  324. to them so you need NO MORE MEMORY TO USE THEM.) Those that
  325. *YOU* create such as linked lists need memory. Your program
  326. when compiled will only allocate 4 bytes for each pointer
  327. (Pointers need 2 words, one for the segment, one for the
  328. offset in that segment) thus the 4 bytes.
  329.  
  330. As a rule of thumb, if you don't create dynamic variables
  331. then you can set the $M to: {$M 16384, 0, 0} which is the
  332. minimum.
  333.  
  334. {$MStack space, minimum heap required to run, Max heap needed}
  335.  
  336. Stack space is the memory needed to hold the stack of your
  337. program, each time you call a function or procedure from
  338. another one, the old adress is pushed onto the stack, it
  339. will pulled off when the called procedure finishes to find
  340. out where to go back and continue executing. Local
  341. variables, parameters are also saved on the stack so they
  342. are not lost or modified while the other procedure is
  343. running.
  344.  
  345. So if you have recursive procedures (procedures that call
  346. themselfes) or use lots of parameters you could set a large
  347. stack. you will find this out through trial and error. If it
  348. doesn't run properly and halts with a *STACK OVERFLOW* error
  349. (TP runtime error 202) then you know you need to increase
  350. the stack space allocated to your program.
  351.  
  352. The second parameter is use IF you create dynamic variables,
  353. it tells TP you need at least this much heap memory free to
  354. run correctly and that it should return to DOS with an error
  355. if at least that much is not free when you try to load your
  356. program.
  357.  
  358. The last paramater is the Maximum heap memory you expect to
  359. use, it can be calculated if you know how much you are going
  360. to use like a big array. If you are using linked lists,
  361. which can not allways be evaluated as to how many items the
  362. list will contain, then you might decide to use it all.
  363. Setting the 3rd parameter to 655360. This won't leave any
  364. room to EXEC another program though.
  365.  
  366. So if you intend to run another program from yours, say
  367. running PKUNZIP from a TP program of yours, then you should
  368. set Maximum Heap to a value lower than 655360. If you know
  369. PKUNZIP needs 55k to run without problems then you could
  370. simply say:
  371.  
  372.         655360 - (55 * 1024) = 599040
  373.  
  374. and set $M to
  375.  
  376. {$M 16384, 0, 599040} this will ensure you have at least 55k
  377. free for PKUNZIP yet giving you the maximum heap space at
  378. the same time.
  379.  
  380. As allways if you don't use dynamic variables at all don't
  381. bother with it simply use
  382.  
  383. {$M 16384, 0, 0} and you will allways have enough memory to
  384. run other programs from your TP programs (Unless you don't
  385. have enough memory to run them from DOS to begin with ;-) )
  386.  
  387.  
  388.         Best regards,
  389.         and a very Happy New Year
  390.         Mark Ouellet.
  391.  
  392.  
  393. --- ME2
  394.  * Origin: BaseBall for Windows, use the disks as bases ;-) (Fidonet 1:240/1.4)
  395. ==============================================================================
  396.  BBS: «« The Info-Tech BBS »»
  397.   To: SHANE RUSSO                  Date: 01-24─92 (15:00)
  398. From: MIKE COPELAND              Number: 5922   [101] $_PASCAL
  399. Subj: TP 6.0 -- MEMORY ALLOCATI  Status: Public
  400. ------------------------------------------------------------------------------
  401.  SR>    Could anyone inform me how to use the $M directive correctly, and
  402.  SR>    what it does exactly?
  403.  
  404.  SR>    Also, what the stack size, heap min and heap max are? (How do you
  405.  SR>    calculate the stack size, heap min and heap max)
  406.  
  407.    There is no absolute, exact answer to this question, since every TP
  408. program has different characteristics and requirements.
  409. However, I will try to give you (and others) some basics, from
  410. which you can probably adjust and use as you learn what's right
  411. for _you_ (every programmer has different styles, which also
  412. affect the way the $M is used):
  413.  
  414.   {$M Stack,Heap_Min,Heap_Max}
  415.  
  416.    The Stack is used within your program for calls to subprograms
  417. (functions and procedures). Its size is dependent on (1) how
  418. deep your calls go (or recurse) and (2) how much parameter and
  419. local data is referenced during these calls. The worst case
  420. I've encountered is a recursive sort of strings, where each
  421. level of call requires all the resident data of the routine and
  422. the parameters passed (string data being so big) are saved on
  423. the Stack - too many levels of such action will exceed the max.
  424. available Stack value, 64K.
  425.    So, if you're not making heavily-nested (or recursive) calls in your
  426. program, you won't need much Stack space - 8192 is probably plenty.
  427.  
  428.    Heap is data _you_ explicitly ask for (unlike the implicit data used
  429. by subprogram calls) - by New, GetMem (in TP), or by calling
  430. library routines which do (therefore, you're not always in
  431. control of this if you're using subroutine libraries you didn't
  432. create). The two parameters stated in the $M are for (1) the
  433. minimum value you want to reserve and (2) the maximum you want to allow.
  434.    I don't know a good reason to ever use any value > 0 for the
  435. Heap_Min parameter, since the runtime will allocate what's
  436. needed (providing the Heap_Max still has something left) -
  437. perhaps performance. So, it's the Heap_Max that's critical for
  438. your consideration.
  439.    I see 2 distinct things here, which are in conflict (and thus
  440. require management of this parameter): dynamic memory use in
  441. your program, and use of the Exec procedure to spawn a child
  442. process. If you don't ever do one of these things, then you have
  443. maximum use of the other; it's that simple 8<}}.
  444.    However (!), doing this is not simple, if you're doing anything
  445. sophistocated with TP. For instance, if you must use data >64K,
  446. you've _got_ to use pointers - which implies dynamic memory
  447. allocation (and consumes the Heap. If, OTOH, you Exec to DOS to
  448. run other programs or DOS calls from within your program, you
  449. must leave sufficient memory for DOS to load that other
  450. program, etc. This, of course, depends on what you're Exec-ing.
  451.    In either case, your program logic and application must determine
  452. how much Heap_Max to reserve. The default is 640K (all of
  453. conventional memory), which prevents _any_ child process
  454. Exec-ing. This default will allow maximum possible use of
  455. dynamic memory (New, GetMem); any need to Exec will require a
  456. reduced value for Heap_Max.
  457.    I often do a bit of both in my programs, and I typically use the
  458. following $M parameter:
  459.  
  460.    {$M 8192,0,128000}
  461.  
  462. and I change either Stack or Heap_Max as I encounter runtime errors
  463. during development. Everyone must do the same, for the reasons
  464. I stated above.
  465.    Note that you _won't_ be able to play with this during development
  466. in the IDE, since that's a program already consuming a LOT of
  467. available memory.
  468.    Hope I made some sense/cleared up some confusion/helped.
  469.  
  470.  
  471. --- msged 2.07
  472.  * Origin: Hello, Keyboard, my old friend... (1:114/18.10)
  473.  
  474.  
  475. ------------------------------------------------------------------------
  476.  
  477. Echo Flag :         Permanent: N       Export: N      Personal Read: N
  478.  
  479.  BBS: IN-TECH         Conference: PASCAL          Imported: 11/11/1991
  480.   To: ZAK SMITH                       Num: 1295       Date: 11/03/1991
  481. From: TREVOR CARLSEN                   Re: 0          Time:  1:58 am
  482. Subj: >NUL REDIRECTION               Prvt: N          Read: N
  483.  
  484.  ZS> Change that to
  485.  ZS> EXEC ('C:\COMMAND.COM','c:\pkzip.exe -o ..... >nul');
  486.  
  487. I'd reckon that will not work on a majority of systems.  Better is ...
  488.  
  489.   exec(GetEnv('COMSPEC'),'c:\pkzip...etc');
  490.  
  491. That way it is not command.com specific.
  492.  
  493. TeeCee
  494.  
  495. --- TC-ED   v2.01  
  496.  * Origin: The Pilbara's Pascal Centre (+61 91 732569) (3:690/644)
  497.  
  498.